package com.ewei.support.mail.javax;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;

import org.budo.mail.Mail;
import org.budo.mail.util.MessageUtil;
import org.budo.support.assertion.Assert;
import org.budo.support.lang.util.StringUtil;
import org.budo.support.lang.util.SystemUtil;
import org.budo.support.slf4j.Slf4j;
import org.slf4j.Logger;

import com.ewei.support.javax.mail.MailSessionUtil;
import com.ewei.support.javax.mail.PasswordAuthenticator;
import com.ewei.support.javax.mail.internet.EweiMimeMessage;
import com.ewei.support.javax.mail.internet.EweiSmtpMessage;
import com.ewei.support.javax.mail.internet.util.InternetAddressUtil;
import com.ewei.support.mail.AbstractMailSender;
import com.sun.mail.smtp.SMTPMessage;

/**
 * @author li
 * @version 1 (2014年7月4日 下午3:23:02)
 * @since Java7
 */
public class JavaxMailSender extends AbstractMailSender {
    private static final Logger log = Slf4j.getLogger();

    private static final String UTF8 = "utf-8";

    private static final String CONTENT_TYPE_HTML_UTF8 = "text/html;charset=utf-8";

    public String send(Mail email) {
        try {
            log.info("#53 doSend email {}", email);

            Session session = this.prepareSession();
            MimeMessage message = this.prepareMessage(email, session);

            Transport.send(message);

            String messageID = message.getMessageID();
            log.info("# after send email {} messageId={}", email, messageID);
            return messageID;
        } catch (Exception e) { // 用户名 发件人不匹配
            String message = e.getMessage() // 
                    + ", sender.username=" + this.getUsername() // 
                    + ", mail.from=" + email.getFrom() // 
                    + ", mail.to=" + email.getTo() // 
                    + ", mail.subject=" + email.getSubject();

            log.error("#70, Transport.send(message) error, message=" + message, e);

            throw new RuntimeException(message, e);
        }
    }

    public Session prepareSession() {
        Properties properties = SystemUtil.getProperties();
        properties.put("mail.smtp.host", Assert.notEmpty(getHost(), "sender.host不可以为空"));
        properties.put("mail.smtp.auth", "true"); // 这样才能通过验证
        properties.put("mail.host", "mail.ewei.com"); // for Message-ID
        properties.put("mail.user", "noreply"); // for Message-ID

        Session session = Session.getInstance(properties, new PasswordAuthenticator(getUsername(), getPassword()));
        session.setDebug(getDebug());
        return session;
    }

    public MimeMessage prepareMessage(Mail mail, Session session) throws MessagingException, AddressException, UnsupportedEncodingException {
        String mailFrom = this.getMailFrom(mail);
        InternetAddress fromAddress = new InternetAddress(mailFrom);

        MimeMessage message;
        if (MailSessionUtil.isSmtp(session, fromAddress)) {
            message = new EweiSmtpMessage(session);
            if (!StringUtil.isEmpty(mail.getSender())) {
                ((SMTPMessage) message).setEnvelopeFrom(mail.getSender()); // sender as MAIL FROM
            }
        } else {
            message = new EweiMimeMessage(session);
        }

        if (!StringUtil.isEmpty(mail.getSender())) {
            message.setSender(new InternetAddress(mail.getSender()));
        }

        message.setSentDate(new Date());
        message.setFrom(fromAddress);

        message.setSubject(mail.getSubject(), UTF8);
        //message.setContent(mail.getContent(), CONTENT_TYPE_HTML_UTF8);
        message.setReplyTo(InternetAddressUtil.toAddressArray(mail.getReplyTo()));
        Multipart multipart = new MimeMultipart();
        MimeBodyPart contentPart = new MimeBodyPart();
        contentPart.setContent(mail.getContent(), CONTENT_TYPE_HTML_UTF8);
        multipart.addBodyPart(contentPart);

        List<File> attachmentList = mail.getAttachmentList();
        if (attachmentList != null && attachmentList.size() > 0) {
            for (int i = 0, len = attachmentList.size(); i < len; i++) {
                File file = attachmentList.get(i);
                MimeBodyPart attachmentPart = new MimeBodyPart();
                FileDataSource source = new FileDataSource(file);
                attachmentPart.setDataHandler(new DataHandler(source));
                attachmentPart.setFileName(MimeUtility.encodeWord(file.getName(), UTF8, null));
                multipart.addBodyPart(attachmentPart);
            }
        }
        message.setContent(multipart);
        MessageUtil.addRecipients(message, RecipientType.TO, StringUtil.split(mail.getTo(), ","));
        MessageUtil.addRecipients(message, RecipientType.CC, StringUtil.split(mail.getCc(), ","));
        MessageUtil.addRecipients(message, RecipientType.BCC, StringUtil.split(mail.getBcc(), ","));

        message.saveChanges();
        return message;
    }

    private String getMailFrom(Mail mail) {
        String from = mail.getFrom();
        return (StringUtil.isEmpty(from) || "null".equalsIgnoreCase(from)) ? this.getFrom() : from;
    }
}